/*
 * $Id: TaskListParser.java,v 1.3 2009/07/21 19:38:53 afaichun Exp $
 * 
 * Copyright (C) 2008 General Electric Company. All Rights Reserved.
 * 
 * This software is the confidential and proprietary information of the General
 * Electric Company (GE). You shall not disclose this software and shall use it
 * only in accordance with the terms of the license agreement you entered into
 * with GE.
 * 
 * GE MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
 * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
 * NON-INFRINGEMENT. GE SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING, OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES.
 */
package com.ge.healthcare.autosc.onwatch.xml.parser;

import java.io.File;
import java.io.IOException;
import java.util.Stack;

import javax.xml.parsers.ParserConfigurationException;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

import com.ge.healthcare.autosc.common.ASCLogger;
import com.ge.healthcare.autosc.common.ASCUtil;
import com.ge.healthcare.autosc.onwatch.xml.tag.AddTaskTag;
import com.ge.healthcare.autosc.onwatch.xml.tag.CommandTag;
import com.ge.healthcare.autosc.onwatch.xml.tag.DeleteTaskTag;
import com.ge.healthcare.autosc.onwatch.xml.tag.DownloadTag;
import com.ge.healthcare.autosc.onwatch.xml.tag.ExecTag;
import com.ge.healthcare.autosc.onwatch.xml.tag.InstallTaskTag;
import com.ge.healthcare.autosc.onwatch.xml.tag.ModifyTaskTag;
import com.ge.healthcare.autosc.onwatch.xml.tag.OnExitTag;
import com.ge.healthcare.autosc.onwatch.xml.tag.ParamTag;
import com.ge.healthcare.autosc.onwatch.xml.tag.PdTag;
import com.ge.healthcare.autosc.onwatch.xml.tag.TaskListTag;
import com.ge.healthcare.autosc.onwatch.xml.tag.TaskRequestInfoTag;
import com.ge.healthcare.autosc.onwatch.xml.tag.TaskRequestTag;
import com.ge.healthcare.autosc.onwatch.xml.tag.UninstallTaskTag;
import com.ge.healthcare.autosc.onwatch.xml.tag.UntarTag;
import com.ge.healthcare.autosc.onwatch.xml.tag.UploadTag;

public class TaskListParser extends BaseXmlParser {

	private static final String TASKLIST_ELEMENT = "taskList";
	private static final String TASK_ELEMENT = "task";
	private static final String INFO_ELEMENT = "info";
	private static final String DEBUG_ELEMENT = "debug";
	private static final String REQUESTOR_ELEMENT = "requestor";
	private static final String EXESCRIPTAS_ELEMENT = "exeScriptAs";
	private static final String COMMAND_ELEMENT = "command";
	private static final String EXEC_ELEMENT = "exec";
	private static final String CMD_ELEMENT = "cmd";
	private static final String PARAM_ELEMENT = "param";
	private static final String DOWNLOAD_ELEMENT = "download";
	private static final String PD_ELEMENT = "pd";
	private static final String INSTALL_TASK_ELEMENT = "installTask";
	private static final String UNINSTALL_TASK_ELEMENT = "unInstallTask";
	private static final String ADD_TASK_ELEMENT = "addTask";
	private static final String DELETE_TASK_ELEMENT = "deleteTask";
	private static final String MODIFY_TASK_ELEMENT = "modifyTask";
	private static final String FILE_ELEMENT = "file";
	private static final String ONEXIT_ELEMENT = "onExit";
	private static final String UNTAR_ELEMENT = "untar";
	private static final String UPLOAD_ELEMENT = "upload";
	private static final String TASK_NAME_ELEMENT = "taskName";
	private static final String DAYOFWEEK_ELEMENT = "dayOfWeek";
	private static final String STARTTIME_ELEMENT = "startTime";
	private static final String ITERATION_ELEMENT = "iteration";
	private TaskListTag taskListTag = null;
	private TaskRequestTag taskRequestTag = null;
	private TaskRequestInfoTag taskRequestInfoTag = null;
	private CommandTag commandTag = null;
	private ExecTag execTag = null;
	private ParamTag paramTag = null;
	private OnExitTag onExitTag = null;
	private DownloadTag downloadTag = null;
	private UntarTag untarTag = null;
	private UploadTag uploadTag = null;
	private PdTag pdTag = null;
	private AddTaskTag addTaskTag = null;
	private DeleteTaskTag deleteTaskTag = null;
	private InstallTaskTag installTaskTag = null;
	private UninstallTaskTag uninstallTaskTag = null;
	private ModifyTaskTag modifyTaskTag = null;
	private Stack<String> elementStack = null;
	
	public TaskListParser(String schemaFileStr) throws ParserConfigurationException, SAXException {
		super(schemaFileStr);
		taskListTag = new TaskListTag();
		elementStack = new Stack<String>();
	}
	
	/**
	 * Selecting the parseElement
	 * 
	 * @see org.xml.sax.ContentHandler#startElement(java.lang.String,
	 *      java.lang.String, java.lang.String, org.xml.sax.Attributes)
	 */
	public void startElement(String strNamespaceURI, String strLocalName,
			String strQName, Attributes attrs) throws SAXException {
		super.startElement(strNamespaceURI, strLocalName, strQName, attrs);
		if (TASKLIST_ELEMENT.equals(strQName)) {
			strParseElement = TASKLIST_ELEMENT;
			taskListTag = new TaskListTag();
			if(!ASCUtil.isNullOrEmpty(attrs.getValue("systemId"))) {
				taskListTag.setSystemId(attrs.getValue("systemId"));
			}
			if(!ASCUtil.isNullOrEmpty(attrs.getValue("modelType"))) {
				taskListTag.setModelType(attrs.getValue("modelType"));
			}
			if(!ASCUtil.isNullOrEmpty(attrs.getValue("iipVersion"))) {
				taskListTag.setIipVersion(attrs.getValue("iipVersion"));
			}
			if(!ASCUtil.isNullOrEmpty(attrs.getValue("id"))) {
				taskListTag.setId(attrs.getValue("id"));
			}
		} else if (TASK_ELEMENT.equals(strQName)) {
			strParseElement = TASK_ELEMENT;
			taskRequestTag = new TaskRequestTag();
			if(!ASCUtil.isNullOrEmpty(attrs.getValue("id"))) {
				taskRequestTag.setId(new Long(attrs.getValue("id")));
			}
		} else if(DEBUG_ELEMENT.equals(strQName)) {
			strParseElement = DEBUG_ELEMENT;
		} else if (INFO_ELEMENT.equals(strQName)) {
			strParseElement = INFO_ELEMENT;
			taskRequestInfoTag = new TaskRequestInfoTag();
		} else if (REQUESTOR_ELEMENT.equals(strQName)) {
			strParseElement = REQUESTOR_ELEMENT;
		} else if (EXESCRIPTAS_ELEMENT.equals(strQName)) {
			strParseElement = EXESCRIPTAS_ELEMENT;
		} else if(COMMAND_ELEMENT.equals(strQName)) {
			strParseElement = COMMAND_ELEMENT;
			commandTag = new CommandTag();
			if(!ASCUtil.isNullOrEmpty(attrs.getValue("startTaskId"))) {
				commandTag.setStartTaskId(attrs.getValue("startTaskId"));
			}
		} else if(EXEC_ELEMENT.equals(strQName)) {
			strParseElement = EXEC_ELEMENT;
			elementStack.push(EXEC_ELEMENT);
			execTag = new ExecTag();
			if(!ASCUtil.isNullOrEmpty(attrs.getValue("id"))) {
				execTag.setId(attrs.getValue("id"));
			} 
			if(!ASCUtil.isNullOrEmpty(attrs.getValue("refId"))) {
				execTag.setRefId(attrs.getValue("refId"));
			} 
			if(!ASCUtil.isNullOrEmpty(attrs.getValue("timeOutSecs"))) {
				execTag.setTimeOutSecs(new Integer(attrs.getValue("timeOutSecs")).intValue());
			} 
			if(!ASCUtil.isNullOrEmpty(attrs.getValue("saveOutput"))) {
				if(attrs.getValue("saveOutput").equalsIgnoreCase("true")) {
					execTag.setSaveOutput(true);
				}
			} 
		} else if(CMD_ELEMENT.equals(strQName)) {
			strParseElement = CMD_ELEMENT;
		} else if(PARAM_ELEMENT.equals(strQName)) {
			strParseElement = PARAM_ELEMENT;
			paramTag = new ParamTag();
			if(!ASCUtil.isNullOrEmpty(attrs.getValue("name"))) {
				paramTag.setName(attrs.getValue("name"));
			}
			if(!ASCUtil.isNullOrEmpty(attrs.getValue("refId"))) {
				paramTag.setRefid(attrs.getValue("refId"));
			}
		} else if(ONEXIT_ELEMENT.equals(strQName)) {
			strParseElement = ONEXIT_ELEMENT;
			onExitTag = new OnExitTag();
			if(!ASCUtil.isNullOrEmpty(attrs.getValue("cond"))) {
				onExitTag.setCond(attrs.getValue("cond"));
			}
			if(!ASCUtil.isNullOrEmpty(attrs.getValue("id"))) {
				onExitTag.setId(attrs.getValue("id"));
			}
		} else if(DOWNLOAD_ELEMENT.equals(strQName)) {
			strParseElement = DOWNLOAD_ELEMENT;
			elementStack.push(DOWNLOAD_ELEMENT);
			downloadTag = new DownloadTag();
			if(!ASCUtil.isNullOrEmpty(attrs.getValue("id"))) {
				downloadTag.setId(attrs.getValue("id"));
			}
		} else if(FILE_ELEMENT.equals(strQName)) {
			strParseElement = FILE_ELEMENT;
		} else if(UNTAR_ELEMENT.equals(strQName)) {
			strParseElement = UNTAR_ELEMENT;
			elementStack.push(UNTAR_ELEMENT);
			untarTag = new UntarTag();
			if(!ASCUtil.isNullOrEmpty(attrs.getValue("id"))) {
				untarTag.setId(attrs.getValue("id"));
			}
		} else if(UPLOAD_ELEMENT.equals(strQName)) {
			strParseElement = UPLOAD_ELEMENT;
			elementStack.push(UPLOAD_ELEMENT);
			uploadTag = new UploadTag();
			if(!ASCUtil.isNullOrEmpty(attrs.getValue("id"))) {
				uploadTag.setId(attrs.getValue("id"));
			}
			if(!ASCUtil.isNullOrEmpty(attrs.getValue("refId"))) {
				uploadTag.setRefId(attrs.getValue("refId"));
			}
			if(!ASCUtil.isNullOrEmpty(attrs.getValue("useContent"))) {
				if(attrs.getValue("useContent").equalsIgnoreCase("true")) {
					uploadTag.setUseContent(true);
				}
			}
		} else if(PD_ELEMENT.equals(strQName)) {
			strParseElement = PD_ELEMENT;
			elementStack.push(PD_ELEMENT);
			pdTag = new PdTag();
			if(!ASCUtil.isNullOrEmpty(attrs.getValue("id"))) {
				pdTag.setId(attrs.getValue("id"));
			}	
			if(!ASCUtil.isNullOrEmpty(attrs.getValue("pdStartTaskId"))) {
				pdTag.setPdStartId(attrs.getValue("pdStartTaskId"));
			}
		} else if(ADD_TASK_ELEMENT.equals(strQName)) {
			strParseElement = ADD_TASK_ELEMENT;
			elementStack.push(ADD_TASK_ELEMENT);
			addTaskTag = new AddTaskTag();
			if(!ASCUtil.isNullOrEmpty(attrs.getValue("id"))) {
				addTaskTag.setId(attrs.getValue("id"));
			}
			if(!ASCUtil.isNullOrEmpty(attrs.getValue("timeOutSecs"))) {
				addTaskTag.setTimeOutSecs(new Integer(attrs.getValue("timeOutSecs")).intValue());
			}
			if(!ASCUtil.isNullOrEmpty(attrs.getValue("nextId"))) {
				addTaskTag.setNextId(attrs.getValue("nextId"));
			}
		} else if(MODIFY_TASK_ELEMENT.equals(strQName)) {
			strParseElement = MODIFY_TASK_ELEMENT;
			elementStack.push(MODIFY_TASK_ELEMENT);
			modifyTaskTag = new ModifyTaskTag();
			if(!ASCUtil.isNullOrEmpty(attrs.getValue("id"))) {
				modifyTaskTag.setId(attrs.getValue("id"));
			}
			if(!ASCUtil.isNullOrEmpty(attrs.getValue("timeOutSecs"))) {
				modifyTaskTag.setTimeOutSecs(new Integer(attrs.getValue("timeOutSecs")).intValue());
			}
			if(!ASCUtil.isNullOrEmpty(attrs.getValue("nextId"))) {
				modifyTaskTag.setNextId(attrs.getValue("nextId"));
			}
		} else if(DELETE_TASK_ELEMENT.equals(strQName)) {
			strParseElement = DELETE_TASK_ELEMENT;
			elementStack.push(DELETE_TASK_ELEMENT);
			deleteTaskTag = new DeleteTaskTag();
			if(!ASCUtil.isNullOrEmpty(attrs.getValue("id"))) {
				deleteTaskTag.setId(attrs.getValue("id"));
			}
			if(!ASCUtil.isNullOrEmpty(attrs.getValue("timeOutSecs"))) {
				deleteTaskTag.setTimeOutSecs(new Integer(attrs.getValue("timeOutSecs")).intValue());
			}
			if(!ASCUtil.isNullOrEmpty(attrs.getValue("nextId"))) {
				deleteTaskTag.setNextId(attrs.getValue("nextId"));
			}
		} else if(INSTALL_TASK_ELEMENT.equals(strQName)) {
			strParseElement = INSTALL_TASK_ELEMENT;
			elementStack.push(INSTALL_TASK_ELEMENT);
			installTaskTag = new InstallTaskTag();
			if(!ASCUtil.isNullOrEmpty(attrs.getValue("id"))) {
				installTaskTag.setId(attrs.getValue("id"));
			}
			if(!ASCUtil.isNullOrEmpty(attrs.getValue("timeOutSecs"))) {
				installTaskTag.setTimeOutSecs(new Integer(attrs.getValue("timeOutSecs")).intValue());
			}
			if(!ASCUtil.isNullOrEmpty(attrs.getValue("nextId"))) {
				installTaskTag.setNextId(attrs.getValue("nextId"));
			}
		} else if(UNINSTALL_TASK_ELEMENT.equals(strQName)) {
			strParseElement = UNINSTALL_TASK_ELEMENT;
			elementStack.push(UNINSTALL_TASK_ELEMENT);
			uninstallTaskTag = new UninstallTaskTag();
			if(!ASCUtil.isNullOrEmpty(attrs.getValue("id"))) {
				uninstallTaskTag.setId(attrs.getValue("id"));
			}
			if(!ASCUtil.isNullOrEmpty(attrs.getValue("timeOutSecs"))) {
				uninstallTaskTag.setTimeOutSecs(new Integer(attrs.getValue("timeOutSecs")).intValue());
			}
			if(!ASCUtil.isNullOrEmpty(attrs.getValue("nextId"))) {
				uninstallTaskTag.setNextId(attrs.getValue("nextId"));
			}
		} else if(TASK_NAME_ELEMENT.equals(strQName)) {
			strParseElement = TASK_NAME_ELEMENT;
		} else if(DAYOFWEEK_ELEMENT.equals(strQName)) {
			strParseElement = DAYOFWEEK_ELEMENT;
		} else if(STARTTIME_ELEMENT.equals(strQName)) {
			strParseElement = STARTTIME_ELEMENT;
		} else if(ITERATION_ELEMENT.equals(strQName)) {
			strParseElement = ITERATION_ELEMENT;
		}
	}
	
	/**
	 * Storing the values
	 * 
	 * @see org.xml.sax.ContentHandler#endElement(java.lang.String,
	 *      java.lang.String, java.lang.String)
	 */
	public void endElement(String strNamespaceURI, String strLocalName,
			String strQName) throws SAXException {
		super.endElement(strNamespaceURI, strLocalName, strQName);
		if (TASK_ELEMENT.equals(strQName)) {
			taskListTag.addTaskRequest(taskRequestTag);
		} else if (INFO_ELEMENT.equals(strQName)) {
			taskRequestTag.setTaskRequestInfo(taskRequestInfoTag);
		} else if (DEBUG_ELEMENT.equals(strQName)) {
			if("true".equalsIgnoreCase(strElementValue)) {
				taskRequestInfoTag.markAsDebug();
				strElementValue = null;
			}
		} else if(REQUESTOR_ELEMENT.equals(strQName)) {
			taskRequestInfoTag.setRequestor(strElementValue);
			strElementValue = null;
		} else if(EXESCRIPTAS_ELEMENT.equals(strQName)) {
			taskRequestInfoTag.setExeScriptAs(strElementValue);
			strElementValue = null;
		} else if(COMMAND_ELEMENT.equals(strQName)) {
			taskRequestTag.setCommandTag(commandTag);
		} else if(EXEC_ELEMENT.equals(strQName)) {
			commandTag.addExec(execTag);
			elementStack.pop();
		} else if(DOWNLOAD_ELEMENT.equals(strQName)) {
			commandTag.addDownload(downloadTag);
			elementStack.pop();
		} else if(UNTAR_ELEMENT.equals(strQName)) {
			commandTag.addUntar(untarTag);
			elementStack.pop();
		} else if(UPLOAD_ELEMENT.equals(strQName)) {
			commandTag.addUpload(uploadTag);
			elementStack.pop();
		} else if(CMD_ELEMENT.equals(strQName)) {
			execTag.setCmd(strElementValue);
			strElementValue = null;
		} else if(PD_ELEMENT.equals(strQName)) {
			commandTag.addPds(pdTag);
			elementStack.pop();
		} else if(ONEXIT_ELEMENT.equals(strQName)) {
			addOnExit();
			strElementValue = null;
		} else if(FILE_ELEMENT.equals(strQName)) {
			addFile();
			strElementValue = null;
		} else if(PARAM_ELEMENT.equals(strQName)) {
			paramTag.setValue(strElementValue);
			execTag.addParam(paramTag);
			strElementValue = null;
		} else if(TASK_NAME_ELEMENT.equals(strQName)) {
			addTaskName();
			strElementValue = null;
		} else if(DAYOFWEEK_ELEMENT.equals(strQName)) {
			addDayOfWeek();
			strElementValue = null;
		} else if(STARTTIME_ELEMENT.equals(strQName)) {
			addStartTime();
			strElementValue = null;
		} else if(ITERATION_ELEMENT.equals(strQName)) {
			addIteration();
			strElementValue = null;
		} else if(INSTALL_TASK_ELEMENT.equals(strQName)) {
			pdTag.addInstallTask(installTaskTag);
			elementStack.pop();
		} else if(UNINSTALL_TASK_ELEMENT.equals(strQName)) {
			pdTag.addUninstallTask(uninstallTaskTag);
			elementStack.pop();
		} else if(ADD_TASK_ELEMENT.equals(strQName)) {
			pdTag.addAddTask(addTaskTag);
			elementStack.pop();
		} else if(MODIFY_TASK_ELEMENT.equals(strQName)) {
			pdTag.addModifyTask(modifyTaskTag);
			elementStack.pop();
		} else if(DELETE_TASK_ELEMENT.equals(strQName)) {
			pdTag.addDeleteTask(deleteTaskTag);
			elementStack.pop();
		}
	}
	
	/**
	 * Extracting the value
	 * 
	 * @see org.xml.sax.ContentHandler#characters(char[], int, int)
	 */
	public void characters(char[] arrCh, int iStart, int iLength)
			throws SAXException {
		super.characters(arrCh, iStart, iLength);
		if (strElementValue != null) {
			strElementValue = new StringBuffer().append(strElementValue)
						.append(new String(arrCh, iStart, iLength)).toString();
		} else {
			strElementValue = new String(arrCh, iStart, iLength);
		}
	}
	
	public void error(SAXParseException spe) throws SAXParseException {
		ASCLogger.fatal(this.getClass(), "error", "Validation failed!!", spe);
		throw spe;	
	}
	
	public TaskListTag processResponse(String strXML) throws SAXException,
			IOException {
		this.parseResponse(strXML);
		return taskListTag;
	}

	public TaskListTag processResponse(File xmlFile) throws SAXException,
			IOException {
		this.parseResponse(xmlFile);
		return taskListTag;
	}

	private void addOnExit() {
		String parentElement = elementStack.peek();
		System.out.println("Parent onExit: " + parentElement);
		if(EXEC_ELEMENT.equals(parentElement)) {
			execTag.addOnExit(onExitTag);
		} else if(DOWNLOAD_ELEMENT.equals(parentElement)) {
			downloadTag.addOnExit(onExitTag);
		} else if(UNTAR_ELEMENT.equals(parentElement)) {
			untarTag.addOnExit(onExitTag);
		} else if(UPLOAD_ELEMENT.equals(parentElement)) {
			uploadTag.addOnExit(onExitTag);
		} else if(PD_ELEMENT.equals(parentElement)) {
			pdTag.addOnExit(onExitTag);
		}
	}
	
	private void addFile() {
		String parentElement = elementStack.peek();
		if(DOWNLOAD_ELEMENT.equals(parentElement)) {
			downloadTag.setFile(strElementValue);
		} else if(UPLOAD_ELEMENT.equals(parentElement)) {
			uploadTag.addFile(strElementValue);
		} else if(UNTAR_ELEMENT.equals(parentElement)) {
			untarTag.setFile(strElementValue);
		} else if(INSTALL_TASK_ELEMENT.equals(parentElement)) {
			installTaskTag.setFile(strElementValue);
		}
	}
	
	private void addTaskName() {
		String parentElement = elementStack.peek();
		if(UNINSTALL_TASK_ELEMENT.equals(parentElement)) {
			uninstallTaskTag.setTaskName(strElementValue);
		} else if(ADD_TASK_ELEMENT.equals(parentElement)) {
			addTaskTag.setTaskName(strElementValue);
		} else if(DELETE_TASK_ELEMENT.equals(parentElement)) {
			deleteTaskTag.setTaskName(strElementValue);
		} else if(MODIFY_TASK_ELEMENT.equals(parentElement)) {
			modifyTaskTag.setTaskName(strElementValue);
		}
	}
	
	private void addDayOfWeek() {
		String parentElement = elementStack.peek();
		if(ADD_TASK_ELEMENT.equals(parentElement)) {
			addTaskTag.setDayOfWeek(strElementValue);
		} else if(MODIFY_TASK_ELEMENT.equals(parentElement)) {
			modifyTaskTag.setDayOfWeek(strElementValue);
		}
	}
	
	private void addStartTime() {
		String parentElement = elementStack.peek();
		if(ADD_TASK_ELEMENT.equals(parentElement)) {
			addTaskTag.setStartTime(strElementValue);
		} else if(MODIFY_TASK_ELEMENT.equals(parentElement)) {
			modifyTaskTag.setStartTime(strElementValue);
		}
	}
	
	private void addIteration() {
		String parentElement = elementStack.peek();
		if(ADD_TASK_ELEMENT.equals(parentElement)) {
			addTaskTag.setIteration(new Integer(strElementValue));
		} else if(MODIFY_TASK_ELEMENT.equals(parentElement)) {
			modifyTaskTag.setIteration(new Integer(strElementValue));
		}
	}
}
